package com.zxhysy.log.annotation.advisor;

import com.zxhysy.log.annotation.context.MethodParameter;
import com.zxhysy.log.annotation.context.MethodResult;
import com.zxhysy.log.annotation.context.NetParameter;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.lang.Nullable;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StopWatch;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;

/**
 * 时间统计的日志调用者
 * @author zhangxinhong
 * @since 2021/9/24 11:18
 */
public class LogMethodInvoker {

    /**
     * 方法启动器
     */
    private final MethodInvocation invocation;

    public LogMethodInvoker(MethodInvocation invocation) {
        this.invocation = invocation;
    }

    /**
     * 执行方法
     * @return 执行结果
     */
    public MethodResult execute() {
        StopWatch stopWatch = new StopWatch();
        MethodResult methodResult = new MethodResult();
        try {
            // 开始执行
            stopWatch.start();
            methodResult.setResult(invocation.proceed());
            methodResult.setSuccess(true);
        } catch (Throwable throwable) {
            // 异常处理
            methodResult.setErrorMsg(throwable.getMessage());
            methodResult.setThrowable(throwable);
            methodResult.setSuccess(false);
        } finally {
            // 结束执行
            stopWatch.stop();
            methodResult.setCostTime(stopWatch.getTotalTimeMillis());
        }
        return methodResult;
    }

    /**
     * 获取方法参数
     * @return 返回方法参数
     */
    public MethodParameter getMethodParameter() {
        return new MethodParameter(invocation.getThis(), invocation.getMethod(), invocation.getArguments());
    }

    /**
     * 获取网络参数
     * @return 网络桉树
     */
    @Nullable
    public NetParameter getNetParameter() {
        HttpServletRequest servletRequest = getHttpRequest();
        if (servletRequest != null) {
            String requestType = servletRequest.getMethod();
            String requestIp = servletRequest.getRemoteAddr();
            String requestUrl = servletRequest.getRequestURI();
            return new NetParameter(requestType, requestIp, requestUrl);
        }
        return null;
    }

    /**
     * 通过上下文获取request信息
     * @return HttpServletRequest
     */
    public static HttpServletRequest getHttpRequest() {
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        return !ObjectUtils.isEmpty(requestAttributes) ? requestAttributes.getRequest() : null;
    }
}
